﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using NUnit.Framework;
using XcoAppSpaces.Contracts.Logging;
using XcoAppSpaces.Contracts.Transport;
using XcoAppSpaces.Serialization.Binary;
using XcoAppSpaces.Transport.Sockets;

namespace test.XcoAppSpaces.Transport.Sockets
{
	[TestFixture]
	public class TimeoutTests
	{
		[Test]
		public void TestConnectionTimeout()
		{
			XcoTCPTransportService.timeoutCheckInterval = 1000; //for easier unittesting

			XcoLoggerFactory.CreateInstance = (t => new TestLogger.TestLogger(true));

			XcoTCPTransportService comm1 = new XcoTCPTransportService(8003);
			XcoBinarySerializer ser1 = new XcoBinarySerializer();
			XcoTCPTransportService comm2 = new XcoTCPTransportService(8004);
			XcoBinarySerializer ser2 = new XcoBinarySerializer();
			ReceivedTmp received = new ReceivedTmp();
			try
			{
				comm1.ConnectionLifetime = TimeSpan.FromSeconds(2);
				comm2.ConnectionLifetime = TimeSpan.FromSeconds(2);

				comm1.OnMessageReceived += received.MessageReceived;
				comm2.OnMessageReceived += received.MessageReceived;
				comm1.Start();
				comm2.Start();
				string addr2 = Environment.MachineName.ToLower() + ":" + 8004;


				byte[] bytes = ser1.Serialize(new IntMsg { value = 1, strValue1 = "123", strValue2 = "test", msgPartList = new List<MsgPart> { new MsgPart { exValue = new Exception(), strValue = "bla" } } });

				comm1.Send(new XcoMessage { Content = bytes, CausalityContext = null }, addr2);

				Thread.Sleep(1500);

				//connections should not yet have timed out
				Assert.AreEqual(1, comm1.ActiveConnections.Count());
				Assert.AreEqual(1, comm2.ActiveConnections.Count());

				Console.WriteLine("Waiting for connection timeout...");
				Thread.Sleep(1500);
				
				Assert.AreEqual(0, comm1.ActiveConnections.Count());
				Assert.AreEqual(0, comm2.ActiveConnections.Count());


				Assert.AreEqual(1, received.Counter);

			}
			catch (Exception ex)
			{
				Console.WriteLine("ERROR: " + ex);

			}
			finally
			{
				comm1.Stop();
				comm2.Stop();
			}
		}
	}
}
